package org.kjtc.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class LuceneUtil {
	public static Map<String, Object> luceneSearch(String searchKey, String searchPath) throws Exception {
		
		Map<String, Object> map = new HashMap<>();
		List<String> list = new ArrayList<String>();
		
		if (searchKey != null && !searchKey.isEmpty()) {
			
			final Path logPath = Paths.get(searchPath);
			if (!Files.isReadable(logPath)) {
				list.add("查询的日志文件读入不可");
			} else {
	            Date beginTime = new Date();

				String logIndexPath = File.separator.concat("tmp").concat(File.separator).concat("index");
				Directory fsDir = FSDirectory.open(Paths.get(logIndexPath));
				
				Analyzer analyzer = new StandardAnalyzer();
		    	QueryParser parser = new QueryParser("contents", analyzer);
		        Query query = parser.parse(searchKey);
		        
				IndexWriter writer = getWriter(fsDir);
		        writer.deleteDocuments(query);
		        addDoc(writer, logPath);
		        writer.close();
		        
		        DirectoryReader reader = DirectoryReader.open(fsDir);
		        IndexSearcher searcher = new IndexSearcher(reader);
		        
		        TopDocs topDocs = searcher.search(query, 1000, Sort.INDEXORDER);
		        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		        
		        if (scoreDocs.length == 0) {
			        list.add("没有查询结果");
		        } else {
		        	System.out.println("查询【" + searchKey + "】的结果：");
		        	for (ScoreDoc scoreDoc : scoreDocs) {
			            Document iDoc = searcher.doc(scoreDoc.doc);
			            list.add(iDoc.get("path"));
			            
			            System.out.println(iDoc.get("path"));
			        }
		        }
		        
		        reader.close();
		        fsDir.close();
		        
		        Date endTime = new Date();
	        	long timeOfSearch = endTime.getTime()-beginTime.getTime();
	        	System.out.println("查询总耗时:" + timeOfSearch + "ms");
			}
	    	
		} else {
			list.add("没有查询结果");
		}
        map.put("path", list);
        return map;
	}
	
	private static void addDoc(final IndexWriter writer, Path path) throws IOException {
		if (Files.isDirectory(path)) {
        	Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                  try {
                	addDoc(writer, path, attrs.lastModifiedTime().toString());
                  } catch (IOException ignore) {
                	  
                  }
                  return FileVisitResult.CONTINUE;
                }
              });
        } else {
        	addDoc(writer, path, Files.getLastModifiedTime(path).toString());
        }
	}
	
	private static void addDoc(IndexWriter writer, Path path, String lastModifiedTime) throws IOException {
		try (InputStream stream = Files.newInputStream(path)) {
			Document doc = new Document();
			doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));
		    doc.add(new StringField("path", path.toString(), Field.Store.YES));
		    writer.addDocument(doc);
		}
	}
	
	private static IndexWriter getWriter(Directory dir) throws Exception {
    	
    	 Analyzer analyzer = new StandardAnalyzer();
         IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
         
         return new IndexWriter(dir, iwc);
    }
}
